package edu.calpoly.csc.coursebook.web;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.w3c.dom.Node;

import com.facebook.api.FacebookException;
import com.facebook.api.FacebookRestClient;

import edu.calpoly.csc.coursebook.Messages;
import edu.calpoly.csc.coursebook.business.model.CourseManager;


/**
 * The callback URL from the Facebook redirection should hit this controller. 
 * For Facebook, make the authentication link to this page:
 * http://[our site address]/test/fbtest.html for now 
 */
public class FacebookController implements Controller 
{

   private static final String api_key = Messages.getString("facebook.APIKEY");
   private static final String secret = Messages.getString("facebook.SECRET");
   private static final String server = Messages.getString("facebook.SERVER");
   
   public static final int SESSION_KEY_INDEX = 0;
   public static final int UID_INDEX = 1;
   
   private String auth_token;
   private String session_key;
   private String uid;
   
   private CourseManager courseMan;
   
   public ModelAndView handleRequest(HttpServletRequest request, 
	                             HttpServletResponse response) 
   throws Exception
   {
      /* facebook will link the user to the "action" that executes this 
       * method. */

      auth_token = request.getParameter("auth_token");
      if (auth_token == null) {
         /* error */
         return null;
      }
      
      FacebookRestClient client;
      List<String> params;
      Document doc;
      NodeList nodes;
      
      client = new FacebookRestClient(server, null, api_key, secret);
      params = new ArrayList<String>();
      params.add("auth_token=" + auth_token);
      try {
         doc = client.callMethod("facebook.auth.getSession", params);
      }
      catch (FacebookException e) {
         /* error in facebook method call */
         return null;
      }
      
      try {
         nodes = doc.getFirstChild().getChildNodes();
      }
      catch (NullPointerException e) {
         /* error in results */
         return null;
      }
      
      session_key = nodes.item(SESSION_KEY_INDEX).getFirstChild().getNodeValue();
      uid = nodes.item(UID_INDEX).getFirstChild().getNodeValue();
      
      client = new FacebookRestClient(server, session_key, api_key, secret);
      params.clear();
      params.add("users=" + uid);
      params.add("fields=interests,first_name,last_name");
      doc = client.callMethod("facebook.users.getInfo", params);
      
      try {
         nodes = doc.getFirstChild().getChildNodes();
         nodes = nodes.item(0).getChildNodes();
      }
      catch (NullPointerException e) {
         /* error in results */
         return null;
      }
      
      Map<String, Object> results = new HashMap<String, Object>();
      String interests = "";
      for (int i = 0; i < nodes.getLength(); i++) {
         Node temp = nodes.item(i);
         String name = temp.getNodeName();
         if (name.equals("first_name"))
            results.put("firstname", temp.getFirstChild().getNodeValue());
         else if (name.equals("last_name"))
            results.put("lastname", temp.getFirstChild().getNodeValue());
         else if (name.equals("interests"))
         {
            interests = temp.getFirstChild().getNodeValue();
            results.put("interests", interests);
         }
      }
      
      results.put("courses", this.getCourseManager().findCourses(interests));
      return new ModelAndView("courses", "model", results);
   }
   
   public void setCourseManager(CourseManager cm)
   {
      this.courseMan = cm;
   }
   
   public CourseManager getCourseManager()
   {
      return this.courseMan;
   }
}